package com.wusiwei.controller;

import com.wusiwei.common.PageResult;
import com.wusiwei.common.Result;
import com.wusiwei.dto.MatchQueryDTO;
import com.wusiwei.entity.Invoice;
import com.wusiwei.entity.Order;
import com.wusiwei.entity.Receipt;
import com.wusiwei.entity.ThreeWayMatch;
import com.wusiwei.service.InvoiceService;
import com.wusiwei.service.MatchService;
import com.wusiwei.service.OrderService;
import com.wusiwei.service.ReceiptService;
import com.wusiwei.vo.MatchField;
import com.wusiwei.vo.MatchResult;
import com.wusiwei.vo.MatchStatisticsData;
import com.wusiwei.vo.MatchedOrderVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;

/**
 * 三单匹配控制器
 */
@RestController
@RequestMapping("/api/match")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "三单匹配", description = "订单、收货单、发票三单匹配相关API接口")
public class MatchController {

    private final MatchService matchService;
    private final InvoiceService invoiceService;
    private final OrderService orderService;
    private final ReceiptService receiptService;

    /**
     * 执行三单匹配
     *
     * @param orderId   订单ID
     * @param receiptId 收货单ID
     * @param invoiceId 发票ID
     * @return 匹配结果
     */
    @PostMapping
    @Operation(summary = "执行三单匹配", description = "根据订单ID、收货单ID和发票ID执行三单匹配")
    public Result<MatchResult> matchThreeDocuments(
            @Parameter(description = "订单ID") @RequestParam String orderId,
            @Parameter(description = "收货单ID") @RequestParam String receiptId,
            @Parameter(description = "发票ID") @RequestParam String invoiceId) {
        try {
            log.info("执行三单匹配, 订单ID: {}, 收货单ID: {}, 发票ID: {}", orderId, receiptId, invoiceId);

            // 转换字符串ID为Long类型
            Long orderIdLong, receiptIdLong, invoiceIdLong;
            try {
                orderIdLong = Long.parseLong(orderId);
                receiptIdLong = Long.parseLong(receiptId);
                invoiceIdLong = Long.parseLong(invoiceId);
            } catch (NumberFormatException e) {
                log.error("ID格式转换错误", e);
                return Result.error("ID格式不正确，应为数字");
            }

            MatchResult result = matchService.matchThreeDocuments(orderIdLong, receiptIdLong, invoiceIdLong);

            // 确保MatchResult中包含订单号、收货单号和发票号
            if (result.getOrderNumber() == null && result.getOrderInfo() != null) {
                result.setOrderNumber(result.getOrderInfo().getOrderNumber());
            }

            if (result.getReceiptNumber() == null && result.getReceiptInfo() != null) {
                result.setReceiptNumber(result.getReceiptInfo().getReceiptNumber());
            }

            if (result.getInvoiceNumber() == null && result.getInvoiceInfo() != null) {
                result.setInvoiceNumber(result.getInvoiceInfo().getInvoiceNumber());
            }

            return Result.success(result);
        } catch (Exception e) {
            log.error("匹配失败", e);
            return Result.error("匹配失败: " + e.getMessage());
        }
    }

    /**
     * 获取匹配记录列表
     *
     * @return 匹配记录列表
     */
    @GetMapping
    @Operation(summary = "获取匹配记录列表", description = "获取所有三单匹配记录")
    public Result<List<ThreeWayMatch>> getAllMatches() {
        try {
            log.info("获取所有匹配记录");
            return matchService.findAll();
        } catch (Exception e) {
            log.error("获取匹配记录列表失败", e);
            return Result.error("获取匹配记录列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID获取匹配记录详情
     *
     * @param id 匹配记录ID
     * @return 匹配记录详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取匹配记录详情", description = "根据ID获取匹配记录详情")
    public Result<MatchedOrderVO> getMatchById(
            @Parameter(description = "匹配记录ID") @PathVariable Long id) {
        try {
            log.info("获取匹配记录详情, ID: {}", id);
            Result<ThreeWayMatch> matchResult = matchService.findById(id);

            if (matchResult.getCode() != 200 || matchResult.getData() == null) {
                log.error("匹配记录不存在或查询失败, 错误信息: {}", matchResult.getMessage());
                return Result.error(matchResult.getMessage() != null ? matchResult.getMessage() : "获取匹配记录详情失败");
            }

            ThreeWayMatch match = matchResult.getData();
            log.info("查询到匹配记录: {}", match);

            // 记录匹配记录中的关键信息
            log.info("匹配记录关键信息: orderId={}, receiptId={}, invoiceId={}, orderNumber={}, receiptNumber={}, invoiceNumber={}, orderAmount={}, receiptAmount={}, invoiceAmount={}, matchTime={}",
                    match.getOrderId(), match.getReceiptId(), match.getInvoiceId(),
                    match.getOrderNumber(), match.getReceiptNumber(), match.getInvoiceNumber(),
                    match.getOrderAmount(), match.getReceiptAmount(), match.getInvoiceAmount(),
                    match.getMatchTime());

            // 查询完整的订单、收货单和发票数据
            Order order = null;
            Receipt receipt = null;
            Invoice invoice = null;

            if (match.getOrderId() != null) {
                order = orderService.getOrderById(match.getOrderId());
                log.info("查询到关联订单: {}", order);

                if (order == null) {
                    log.warn("未能查询到关联订单，orderId={}", match.getOrderId());
                } else {
                    log.info("订单关键信息: orderNumber={}, totalAmount={}, status={}, supplierName={}",
                            order.getOrderNumber(), order.getTotalAmount(), order.getStatus(), order.getSupplierName());
                }
            } else {
                log.warn("匹配记录中缺少订单ID");
            }

            if (match.getReceiptId() != null) {
                receipt = receiptService.getReceiptById(match.getReceiptId());
                log.info("查询到关联收货单: {}", receipt);

                if (receipt == null) {
                    log.warn("未能查询到关联收货单，receiptId={}", match.getReceiptId());
                } else {
                    log.info("收货单关键信息: receiptNumber={}, totalAmount={}, status={}, supplierName={}",
                            receipt.getReceiptNumber(), receipt.getTotalAmount(), receipt.getStatus(), receipt.getSupplierName());
                }
            } else {
                log.warn("匹配记录中缺少收货单ID");
            }

            if (match.getInvoiceId() != null) {
                Result<Invoice> invoiceResult = invoiceService.findById(match.getInvoiceId());
                if (invoiceResult.getCode() == 200 && invoiceResult.getData() != null) {
                    invoice = invoiceResult.getData();
                    log.info("查询到关联发票: {}", invoice);
                    log.info("发票关键信息: invoiceNumber={}, totalAmount={}, supplierName={}",
                            invoice.getInvoiceNumber(), invoice.getTotalAmount(), invoice.getSupplierName());
                } else {
                    log.warn("未能查询到关联发票，invoiceId={}, 错误信息: {}", match.getInvoiceId(), invoiceResult.getMessage());
                }
            } else {
                log.warn("匹配记录中缺少发票ID");
            }

            // 构建匹配订单视图对象，包含完整信息
            MatchedOrderVO matchedOrderVO = new MatchedOrderVO();

            // 订单信息
            if (order != null) {
                matchedOrderVO.setOrderId(order.getId());
                matchedOrderVO.setOrderNumber(order.getOrderNumber());
                matchedOrderVO.setOrderAmount(order.getTotalAmount());
                matchedOrderVO.setOrderStatus(order.getStatus());
                matchedOrderVO.setPurchaseDate(order.getPurchaseDate());
                matchedOrderVO.setSupplierName(order.getSupplierName());
            } else {
                matchedOrderVO.setOrderId(match.getOrderId());
                matchedOrderVO.setOrderNumber(match.getOrderNumber());
                matchedOrderVO.setSupplierName(match.getSupplierName());
                // 使用匹配记录中的订单金额
                matchedOrderVO.setOrderAmount(match.getOrderAmount());
            }

            // 收货单信息
            if (receipt != null) {
                matchedOrderVO.setReceiptId(receipt.getId());
                matchedOrderVO.setReceiptNumber(receipt.getReceiptNumber());
                matchedOrderVO.setReceiptAmount(receipt.getTotalAmount());
                matchedOrderVO.setReceiptStatus(receipt.getStatus());
            } else {
                matchedOrderVO.setReceiptId(match.getReceiptId());
                matchedOrderVO.setReceiptNumber(match.getReceiptNumber());
                // 使用匹配记录中的收货单金额
                matchedOrderVO.setReceiptAmount(match.getReceiptAmount());
            }

            // 发票信息
            if (invoice != null) {
                matchedOrderVO.setInvoiceId(invoice.getId());
                matchedOrderVO.setInvoiceNumber(invoice.getInvoiceNumber());
                matchedOrderVO.setInvoiceAmount(invoice.getTotalAmount());
                matchedOrderVO.setIssueDate(invoice.getIssueDate());
            } else {
                matchedOrderVO.setInvoiceId(match.getInvoiceId());
                matchedOrderVO.setInvoiceNumber(match.getInvoiceNumber());
                // 使用匹配记录中的发票金额
                matchedOrderVO.setInvoiceAmount(match.getInvoiceAmount());
            }

            // 匹配信息
            matchedOrderVO.setMatchId(match.getId());
            matchedOrderVO.setMatchResult(match.getMatchResult());
            matchedOrderVO.setDifference(match.getDifference());

            // 优先使用matchTime，如果为空则使用createTime
            matchedOrderVO.setMatchTime(match.getMatchTime() != null ? match.getMatchTime() : match.getCreateTime());

            // 设置金额确保不为null
            if (matchedOrderVO.getOrderAmount() == null) {
                matchedOrderVO.setOrderAmount(BigDecimal.ZERO);
                log.warn("订单金额为null，已设置为0");
            }

            if (matchedOrderVO.getReceiptAmount() == null) {
                matchedOrderVO.setReceiptAmount(BigDecimal.ZERO);
                log.warn("收货单金额为null，已设置为0");
            }

            if (matchedOrderVO.getInvoiceAmount() == null) {
                matchedOrderVO.setInvoiceAmount(BigDecimal.ZERO);
                log.warn("发票金额为null，已设置为0");
            }

            log.info("构建的匹配详情VO: {}", matchedOrderVO);

            // 记录最终返回的关键数据
            log.info("返回给前端的关键数据: orderId={}, orderNumber={}, orderAmount={}, receiptId={}, receiptNumber={}, receiptAmount={}, invoiceId={}, invoiceNumber={}, invoiceAmount={}, matchResult={}, matchTime={}",
                    matchedOrderVO.getOrderId(), matchedOrderVO.getOrderNumber(), matchedOrderVO.getOrderAmount(),
                    matchedOrderVO.getReceiptId(), matchedOrderVO.getReceiptNumber(), matchedOrderVO.getReceiptAmount(),
                    matchedOrderVO.getInvoiceId(), matchedOrderVO.getInvoiceNumber(), matchedOrderVO.getInvoiceAmount(),
                    matchedOrderVO.getMatchResult(), matchedOrderVO.getMatchTime());

            return Result.success(matchedOrderVO);
        } catch (Exception e) {
            log.error("获取匹配记录详情失败", e);
            return Result.error("获取匹配记录详情失败: " + e.getMessage());
        }
    }

    /**
     * 分页查询匹配记录
     *
     * @param pageNum      页码
     * @param pageSize     每页大小
     * @param supplierName 供应商名称
     * @param matchResult  匹配结果
     * @param startDate    开始日期
     * @param endDate      结束日期
     * @return 匹配记录分页结果
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询匹配记录", description = "分页查询匹配记录")
    public Result<Object> getMatchPage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") int pageSize,
            @Parameter(description = "供应商名称") @RequestParam(required = false) String supplierName,
            @Parameter(description = "匹配结果") @RequestParam(required = false) String matchResult,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) {
        try {
            log.info("分页查询匹配记录, 页码: {}, 每页大小: {}, 供应商: {}, 匹配结果: {}, 日期范围: {} - {}",
                    pageNum, pageSize, supplierName, matchResult, startDate, endDate);
            Object pageResult = matchService.getMatchPage(pageNum, pageSize, supplierName, matchResult, startDate, endDate);
            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("分页查询匹配记录失败", e);
            return Result.error("分页查询匹配记录失败: " + e.getMessage());
        }
    }

    /**
     * 获取匹配统计数据
     *
     * @param startDate    开始日期
     * @param endDate      结束日期
     * @param supplierName 供应商名称
     * @param documentType 单据类型
     * @return 匹配统计数据
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取匹配统计数据", description = "获取匹配统计数据")
    public Result<Object> getMatchStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate,
            @Parameter(description = "供应商名称") @RequestParam(required = false) String supplierName,
            @Parameter(description = "单据类型") @RequestParam(required = false) String documentType) {
        try {
            log.info("获取匹配统计数据：开始日期={}, 结束日期={}, 供应商={}, 单据类型={}",
                    startDate, endDate, supplierName, documentType);

            // 如果是yyyy格式，说明是年份，转换为startDate和endDate
            if (startDate != null && startDate.matches("\\d{4}")) {
                String year = startDate;
                log.info("检测到年份格式: {}, 将转换为日期范围", year);
                startDate = year + "-01-01";
                endDate = year + "-12-31";
                log.info("转换后日期范围: {} 到 {}", startDate, endDate);
            }

            // 构建查询参数
            MatchQueryDTO queryDTO = new MatchQueryDTO();

            // 设置日期范围
            if (startDate != null && !startDate.isEmpty()) {
                queryDTO.setStartDate(LocalDate.parse(startDate));
            }

            if (endDate != null && !endDate.isEmpty()) {
                queryDTO.setEndDate(LocalDate.parse(endDate));
            }

            // 设置供应商
            queryDTO.setSupplierName(supplierName);

            // 获取统计数据
            MatchStatisticsData data = matchService.getMatchStatistics(queryDTO);

            return Result.success(data);
        } catch (Exception e) {
            log.error("获取匹配统计数据失败", e);
            return Result.error("获取匹配统计数据失败: " + e.getMessage());
        }
    }

    /**
     * 获取供应商匹配准确率
     *
     * @return 供应商匹配准确率列表
     */
    @GetMapping("/supplier-rate")
    @Operation(summary = "获取供应商匹配准确率", description = "获取各供应商的匹配准确率统计")
    public Result<List<Map<String, Object>>> getSupplierMatchRate() {
        try {
            log.info("获取供应商匹配准确率");
            Map<String, Object> statistics = matchService.getMatchStatistics();
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> rateList = (List<Map<String, Object>>) statistics.get("supplierMatchRate");
            return Result.success(rateList);
        } catch (Exception e) {
            log.error("获取供应商匹配准确率失败", e);
            return Result.error("获取供应商匹配准确率失败: " + e.getMessage());
        }
    }

    /**
     * 获取匹配结果趋势
     *
     * @return 匹配结果趋势数据
     */
    @GetMapping("/trend")
    @Operation(summary = "获取匹配结果趋势", description = "获取按月度统计的匹配结果趋势")
    public Result<List<Map<String, Object>>> getMatchTrend() {
        try {
            log.info("获取匹配结果趋势");
            Map<String, Object> statistics = matchService.getMatchStatistics();
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> trend = (List<Map<String, Object>>) statistics.get("monthlyTrend");
            return Result.success(trend);
        } catch (Exception e) {
            log.error("获取匹配结果趋势失败", e);
            return Result.error("获取匹配结果趋势失败: " + e.getMessage());
        }
    }

    /**
     * 删除匹配记录
     *
     * @param id 匹配记录ID
     * @return 操作结果
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除匹配记录", description = "根据ID删除匹配记录")
    public Result<Boolean> deleteMatch(
            @Parameter(description = "匹配记录ID") @PathVariable Long id) {
        try {
            log.info("删除匹配记录, ID: {}", id);
            Result<Void> result = matchService.delete(id);
            if (result.getCode() == 200) {
                return Result.success(true);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("删除匹配记录失败", e);
            return Result.error("删除匹配记录失败: " + e.getMessage());
        }
    }

    /**
     * 导出匹配记录
     *
     * @param supplierName 供应商名称
     * @param matchResult  匹配结果
     * @param startDate    开始日期
     * @param endDate      结束日期
     * @return 导出的文件
     */
    @GetMapping("/export")
    @Operation(summary = "导出匹配记录", description = "将匹配记录导出为Excel文件")
    public ResponseEntity<?> exportMatches(
            @Parameter(description = "供应商名称") @RequestParam(required = false) String supplierName,
            @Parameter(description = "匹配结果") @RequestParam(required = false) String matchResult,
            @Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam(required = false) String endDate,
            @RequestHeader(value = "Authorization", required = false) String authHeader) {
        try {
            log.info("导出匹配记录, 供应商: {}, 匹配结果: {}, 日期范围: {} - {}",
                    supplierName, matchResult, startDate, endDate);

            // 记录认证头信息（隐藏部分敏感信息）
            if (authHeader != null && !authHeader.isEmpty()) {
                if (authHeader.length() > 15) {
                    log.info("收到认证头: {}...{}", authHeader.substring(0, 10), authHeader.substring(authHeader.length() - 5));
                } else {
                    log.info("收到认证头: [头信息太短，可能无效]");
                }
            } else {
                log.warn("导出请求中没有认证头");
            }

            // 获取当前认证用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

            // 记录认证信息
            if (authentication != null) {
                log.info("认证信息: isAuthenticated={}, principal={}, authorities={}",
                        authentication.isAuthenticated(),
                        authentication.getPrincipal(),
                        authentication.getAuthorities());
            } else {
                log.warn("无认证信息");
            }

            // 修改：临时关闭严格的身份验证要求，直接进行导出
            // 在生产环境中应移除此代码，恢复身份验证
            // 如果要测试身份验证功能，请注释掉以下代码块
            /*
            if (authentication == null || !authentication.isAuthenticated() ||
                    authentication.getPrincipal().equals("anonymousUser")) {
                log.warn("导出匹配记录失败: 用户未认证");

                // 返回明确的401错误，前端不会尝试刷新token
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                headers.setCacheControl("no-cache, no-store, must-revalidate");
                // 添加CORS头
                headers.add("Access-Control-Allow-Origin", "*");
                headers.add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization");

                return ResponseEntity
                        .status(HttpStatus.UNAUTHORIZED)
                        .headers(headers)
                        .body("{\"code\":401,\"message\":\"登录已过期，请重新登录后再尝试导出\",\"success\":false}");
            }
            */

            // 如果有认证信息，记录用户名
            if (authentication != null && authentication.isAuthenticated() &&
                    !authentication.getPrincipal().equals("anonymousUser")) {
                log.info("授权用户: {}", authentication.getName());
            } else {
                log.info("未授权用户访问，但仍允许导出（测试模式）");
            }

            byte[] fileContent = matchService.exportMatches(supplierName, matchResult, startDate, endDate);

            if (fileContent == null || fileContent.length == 0) {
                log.warn("导出匹配记录数据为空");
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                // 不再手动添加CORS头，使用全局配置

                return ResponseEntity.status(HttpStatus.NO_CONTENT)
                        .headers(headers)
                        .body("{\"code\":204,\"message\":\"没有可导出的数据\",\"success\":false}");
            }

            log.info("成功生成导出文件，大小: {} 字节", fileContent.length);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            // 使用更简单的文件名，并确保文件名不包含特殊字符
            String fileName = "匹配记录_" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xlsx";
            String encodedFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); // 处理中文文件名
            headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");
            // 添加缓存控制和下载属性
            headers.setCacheControl("no-cache, no-store, must-revalidate");
            headers.setPragma("no-cache");
            headers.setExpires(0);
            // 不再手动添加CORS头，使用全局配置
            headers.add("Access-Control-Expose-Headers", "Content-Disposition, Content-Type, Content-Length");

            log.info("导出匹配记录成功，返回Excel文件，文件名: {}", fileName);

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(fileContent);
        } catch (Exception e) {
            log.error("导出匹配记录失败: {}", e.getMessage(), e);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // 不再手动添加CORS头，使用全局配置

            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .headers(headers)
                    .body("{\"code\":500,\"message\":\"导出匹配记录失败: " + e.getMessage() + "\",\"success\":false}");
        }
    }

    /**
     * 根据发票ID自动匹配
     *
     * @param invoiceId 发票ID
     * @return 匹配结果
     */
    @PostMapping("/auto-match")
    @Operation(summary = "自动匹配", description = "根据发票ID自动查找合适的订单和收货单并进行匹配")
    public Result<MatchResult> autoMatch(
            @Parameter(description = "发票ID") @RequestParam Long invoiceId) {
        try {
            log.info("开始自动匹配流程, 发票ID: {}", invoiceId);

            // 1. 查询发票信息
            Invoice invoice = invoiceService.getById(invoiceId);
            if (invoice == null) {
                return Result.error("发票不存在，ID: " + invoiceId);
            }

            // 2. 根据发票中的订单ID和收货单ID进行匹配
            if (invoice.getOrderId() != null && invoice.getReceiptId() != null) {
                log.info("发票已关联订单ID: {}和收货单ID: {}, 直接进行匹配", invoice.getOrderId(), invoice.getReceiptId());
                MatchResult result = matchService.matchThreeDocuments(invoice.getOrderId(), invoice.getReceiptId(), invoiceId);
                return Result.success(result);
            }

            // 3. 根据供应商名称和金额查找可能匹配的订单和收货单
            log.info("发票未关联订单和收货单，开始根据供应商和金额查找匹配项, 供应商: {}, 金额: {}",
                    invoice.getSupplierName(), invoice.getTotalAmount());

            // 3.1 查找匹配的订单
            List<Order> orders = orderService.getAllOrders().stream()
                    .filter(o -> o.getSupplierName() != null &&
                            o.getSupplierName().contains(invoice.getSupplierName()) &&
                            o.getTotalAmount() != null &&
                            o.getTotalAmount().subtract(invoice.getTotalAmount()).abs().compareTo(new BigDecimal("0.01")) < 0)
                    .toList();

            // 3.2 查找匹配的收货单
            List<Receipt> receipts = receiptService.getAllReceipts().stream()
                    .filter(r -> r.getSupplierName() != null &&
                            r.getSupplierName().contains(invoice.getSupplierName()) &&
                            r.getTotalAmount() != null &&
                            r.getTotalAmount().subtract(invoice.getTotalAmount()).abs().compareTo(new BigDecimal("0.01")) < 0)
                    .toList();

            log.info("找到可能匹配的订单: {}个, 收货单: {}个",
                    orders.size(), receipts.size());

            // 4. 如果找到匹配的订单和收货单，执行匹配
            if (!orders.isEmpty() && !receipts.isEmpty()) {
                // 取第一个匹配的订单和收货单进行匹配
                Order matchedOrder = orders.get(0);
                Receipt matchedReceipt = receipts.get(0);

                log.info("选择订单ID: {}和收货单ID: {}进行自动匹配",
                        matchedOrder.getId(), matchedReceipt.getId());

                // 执行匹配
                MatchResult result = matchService.matchThreeDocuments(
                        matchedOrder.getId(), matchedReceipt.getId(), invoiceId);
                return Result.success(result);
            }

            return Result.error("无法找到匹配的订单和收货单");
        } catch (Exception e) {
            log.error("自动匹配失败", e);
            return Result.error("自动匹配失败: " + e.getMessage());
        }
    }

    /**
     * 全局自动匹配
     * 自动查找数据库中可以匹配的订单、收货单和发票并执行匹配
     *
     * @return 匹配结果列表
     */
    @PostMapping("/global-match")
    @Operation(summary = "全局自动匹配", description = "自动查找数据库中可以匹配的订单、收货单和发票并执行匹配")
    public Result<List<Map<String, Object>>> globalMatch() {
        try {
            log.info("执行全局自动匹配");
            List<MatchResult> matchResults = matchService.performGlobalMatch();
            log.info("全局自动匹配完成，得到{}条匹配结果", matchResults.size());

            // 转换结果为前端需要的格式
            List<Map<String, Object>> results = new ArrayList<>();
            for (MatchResult result : matchResults) {
                Map<String, Object> matchMap = new HashMap<>();
                matchMap.put("matchResult", result.isMatch() ? "匹配" : "不匹配");
                // 添加match字段，用于前端判断匹配结果
                matchMap.put("match", result.isMatch());

                // 尝试从字段级匹配信息中提取金额
                BigDecimal orderAmount = null;
                BigDecimal receiptAmount = null;
                BigDecimal invoiceAmount = null;

                if (result.getFields() != null) {
                    for (MatchField field : result.getFields()) {
                        if ("金额".equals(field.getFieldName())) {
                            try {
                                if (field.getOrderValue() != null && !"未知".equals(field.getOrderValue())) {
                                    orderAmount = new BigDecimal(field.getOrderValue());
                                }
                                if (field.getReceiptValue() != null && !"未知".equals(field.getReceiptValue())) {
                                    receiptAmount = new BigDecimal(field.getReceiptValue());
                                }
                                if (field.getInvoiceValue() != null && !"未知".equals(field.getInvoiceValue())) {
                                    invoiceAmount = new BigDecimal(field.getInvoiceValue());
                                }
                            } catch (NumberFormatException e) {
                                log.warn("无法解析金额字符串为BigDecimal: {}", e.getMessage());
                            }
                        }
                    }
                }

                // 填充订单信息
                if (result.getOrderInfo() != null) {
                    matchMap.put("orderId", result.getOrderInfo().getId());
                    matchMap.put("orderNumber", result.getOrderInfo().getOrderNumber());
                    matchMap.put("orderAmount", result.getOrderInfo().getTotalAmount());
                } else {
                    // 确保即使没有订单信息也设置orderNumber字段
                    matchMap.put("orderId", "");
                    matchMap.put("orderNumber", result.getOrderNumber() != null ? result.getOrderNumber() : "暂无");
                    matchMap.put("orderAmount", orderAmount != null ? orderAmount : 0);
                }

                // 填充收货单信息
                if (result.getReceiptInfo() != null) {
                    matchMap.put("receiptId", result.getReceiptInfo().getId());
                    matchMap.put("receiptNumber", result.getReceiptInfo().getReceiptNumber());
                    matchMap.put("receiptAmount", result.getReceiptInfo().getTotalAmount());
                } else {
                    // 确保即使没有收货单信息也设置receiptNumber字段
                    matchMap.put("receiptId", "");
                    matchMap.put("receiptNumber", result.getReceiptNumber() != null ? result.getReceiptNumber() : "暂无");
                    matchMap.put("receiptAmount", receiptAmount != null ? receiptAmount : 0);
                }

                // 填充发票信息
                if (result.getInvoiceInfo() != null) {
                    matchMap.put("invoiceId", result.getInvoiceInfo().getId());
                    matchMap.put("invoiceNumber", result.getInvoiceInfo().getInvoiceNumber());
                    matchMap.put("supplierName", result.getInvoiceInfo().getSupplierName());
                    matchMap.put("invoiceAmount", result.getInvoiceInfo().getTotalAmount());
                    // 添加可用于显示的总金额字段
                    matchMap.put("totalAmount", result.getInvoiceInfo().getTotalAmount());
                } else {
                    // 确保即使没有发票信息也设置invoiceNumber和supplierName字段
                    matchMap.put("invoiceId", "");
                    matchMap.put("invoiceNumber", result.getInvoiceNumber() != null ? result.getInvoiceNumber() : "暂无");
                    matchMap.put("supplierName", result.getSupplierName() != null ? result.getSupplierName() : "暂无");
                    matchMap.put("invoiceAmount", invoiceAmount != null ? invoiceAmount : 0);
                    // 添加默认总金额
                    matchMap.put("totalAmount", invoiceAmount != null ? invoiceAmount : 0);
                }

                // 确保设置匹配时间
                matchMap.put("matchTime", result.getMatchTime() != null ? result.getMatchTime().toString() : "");

                // 添加额外的说明信息（如果有）
                if (result.getReason() != null && !result.getReason().isEmpty()) {
                    matchMap.put("reason", result.getReason());
                } else {
                    matchMap.put("reason", "");
                }

                results.add(matchMap);
            }

            log.info("全局匹配返回前端数据: {}", results);
            return Result.success(results);
        } catch (Exception e) {
            log.error("全局自动匹配失败", e);
            return Result.error("全局自动匹配失败: " + e.getMessage());
        }
    }

    /**
     * 获取可三单匹配的订单列表（未在三单匹配表中的订单）
     *
     * @param pageNum      页码
     * @param pageSize     每页大小
     * @param supplierName 供应商名称
     * @param orderNumber  订单编号
     * @param startDate    开始日期
     * @param endDate      结束日期
     * @return 可匹配的订单列表
     */
    @GetMapping("/available-orders")
    @Operation(summary = "获取可三单匹配的订单列表", description = "查询未进行过三单匹配的订单")
    public Result<PageResult<Order>> getOrdersAvailableForMatch(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") int pageSize,
            @Parameter(description = "供应商名称") @RequestParam(required = false) String supplierName,
            @Parameter(description = "订单编号") @RequestParam(required = false) String orderNumber,
            @Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam(required = false) String endDate) {
        try {
            log.info("获取可三单匹配的订单列表, 页码: {}, 每页大小: {}, 供应商: {}, 订单编号: {}, 日期范围: {} - {}",
                    pageNum, pageSize, supplierName, orderNumber, startDate, endDate);

            PageResult<Order> pageResult = matchService.getOrdersAvailableForMatch(
                    pageNum, pageSize, supplierName, orderNumber, startDate, endDate);

            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("获取可三单匹配的订单列表失败", e);
            return Result.error("获取可三单匹配的订单列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取已完成三单匹配的订单列表
     *
     * @param pageNum      页码
     * @param pageSize     每页大小
     * @param supplierName 供应商名称
     * @param orderNumber  订单编号
     * @param matchResult  匹配结果
     * @param startDate    开始日期
     * @param endDate      结束日期
     * @return 已匹配的订单列表
     */
    @GetMapping("/matched-orders")
    @Operation(summary = "获取已完成三单匹配的订单列表", description = "查询已进行过三单匹配的订单")
    public Result<PageResult<MatchedOrderVO>> getMatchedOrders(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") int pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") int pageSize,
            @Parameter(description = "供应商名称") @RequestParam(required = false) String supplierName,
            @Parameter(description = "订单编号") @RequestParam(required = false) String orderNumber,
            @Parameter(description = "匹配结果") @RequestParam(required = false) String matchResult,
            @Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam(required = false) String endDate) {
        try {
            log.info("获取已完成三单匹配的订单列表, 页码: {}, 每页大小: {}, 供应商: {}, 订单编号: {}, 匹配结果: {}, 日期范围: {} - {}",
                    pageNum, pageSize, supplierName, orderNumber, matchResult, startDate, endDate);

            PageResult<MatchedOrderVO> pageResult = matchService.getMatchedOrders(
                    pageNum, pageSize, supplierName, orderNumber, matchResult, startDate, endDate);

            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("获取已完成三单匹配的订单列表失败", e);
            return Result.error("获取已完成三单匹配的订单列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取可与指定订单匹配的收货单和发票
     *
     * @param orderId 订单ID
     * @return 可匹配的收货单和发票
     */
    @GetMapping("/match-candidates/{orderId}")
    @Operation(summary = "获取可与指定订单匹配的收货单和发票", description = "根据订单ID查询可以用于三单匹配的收货单和发票")
    public Result<Map<String, Object>> getMatchCandidates(
            @Parameter(description = "订单ID") @PathVariable Long orderId) {
        try {
            log.info("获取可与订单ID={}匹配的收货单和发票", orderId);

            // 获取可匹配的收货单列表
            List<Receipt> receipts = matchService.getReceiptsForOrderMatch(orderId);

            // 获取可匹配的发票列表
            List<Invoice> invoices = matchService.getInvoicesForOrderMatch(orderId);

            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("receipts", receipts);
            result.put("invoices", invoices);
            result.put("receiptCount", receipts.size());
            result.put("invoiceCount", invoices.size());

            return Result.success(result);
        } catch (Exception e) {
            log.error("获取可匹配的收货单和发票失败", e);
            return Result.error("获取可匹配的收货单和发票失败: " + e.getMessage());
        }
    }

    /**
     * 批量删除匹配记录
     *
     * @param requestBody 匹配记录ID列表
     * @return 操作结果
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除匹配记录", description = "批量删除多个匹配记录")
    public Result<Boolean> batchDeleteMatch(
            @Parameter(description = "匹配记录ID列表") @RequestBody Map<String, List<Long>> requestBody) {
        try {
            List<Long> ids = requestBody.get("ids");
            if (ids == null || ids.isEmpty()) {
                return Result.error("匹配记录ID列表不能为空");
            }

            log.info("批量删除匹配记录, IDs: {}", ids);
            boolean success = matchService.batchDelete(ids);

            if (success) {
                return Result.success(true);
            } else {
                return Result.error("部分或全部匹配记录删除失败");
            }
        } catch (Exception e) {
            log.error("批量删除匹配记录失败", e);
            return Result.error("批量删除匹配记录失败: " + e.getMessage());
        }
    }

    /**
     * 自动匹配（根据单号）
     *
     * @param data 匹配参数
     * @return 匹配结果
     */
    @PostMapping("/auto")
    @Operation(summary = "自动匹配（根据单号）", description = "根据订单号、收货单号或发票号自动匹配")
    public Result<MatchResult> autoMatchByCode(@RequestBody Map<String, String> data) {
        try {
            String invoiceCode = data.get("invoiceCode");
            String receiptCode = data.get("receiptCode");
            String orderCode = data.get("orderCode");

            log.info("根据单号自动匹配, 发票号: {}, 收货单号: {}, 订单号: {}", invoiceCode, receiptCode, orderCode);

            MatchResult result = matchService.autoMatchByCode(orderCode, receiptCode, invoiceCode);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据单号自动匹配失败", e);
            return Result.error("根据单号自动匹配失败: " + e.getMessage());
        }
    }

    /**
     * 更新匹配记录
     *
     * @param id   匹配记录ID
     * @param data 匹配数据
     * @return 更新后的匹配记录
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新匹配记录", description = "根据ID更新匹配记录")
    public Result<ThreeWayMatch> updateMatch(
            @Parameter(description = "匹配记录ID") @PathVariable Long id,
            @RequestBody ThreeWayMatch data) {
        try {
            log.info("更新匹配记录, ID: {}, 数据: {}", id, data);
            data.setId(id); // 确保ID正确设置
            return matchService.update(data);
        } catch (Exception e) {
            log.error("更新匹配记录失败, ID: {}", id, e);
            return Result.error("更新匹配记录失败: " + e.getMessage());
        }
    }
} 